#include "ADXL345.h"


#include "stdint.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "getopt.h"
#include "fcntl.h"
#include "string.h"
#include "sys/ioctl.h"
#include "linux/types.h"
#include "linux/spi/spidev.h"


#define WCMD(arg)       (arg&0x7F) 
#define RCMD(arg)      (arg|0x80)
#define RXSIZE              12
#define TXSIZE              12

static const char *device = "/dev/spidev0.1";
int dev_spi_fd;
static uint8_t dev_spi_mode = 3;
static uint8_t dev_spi_bits = 8;
static uint32_t dev_spi_speed = 5000000;

int gpioValuefd=-1;

unsigned char gtx[TXSIZE];
unsigned char grx[RXSIZE];



static void Spi_Init()
{
    int ret = 0;
    int exportGpio=0;
    dev_spi_fd = open(device, O_RDWR);
    if (dev_spi_fd < 0)
        LOG_ERROR("can't open device\n");

    /* spi mode */
    ret = ioctl(dev_spi_fd, SPI_IOC_WR_MODE, &dev_spi_mode);
    if (ret == -1)
        LOG_ERROR("can't set spi mode\n");

    ret = ioctl(dev_spi_fd, SPI_IOC_RD_MODE, &dev_spi_mode);
    if (ret == -1)
        LOG_ERROR("can't get spi mode\n");

    /* bits per word */
    ret = ioctl(dev_spi_fd, SPI_IOC_WR_BITS_PER_WORD, &dev_spi_bits);
    if (ret == -1)
        LOG_ERROR("can't set bits per word\n");

    ret = ioctl(dev_spi_fd, SPI_IOC_RD_BITS_PER_WORD, &dev_spi_bits);
    if (ret == -1)
        LOG_ERROR("can't get bits per word\n");

    /* max speed hz */
    ret = ioctl(dev_spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &dev_spi_speed);
    if (ret == -1)
        LOG_ERROR("can't set max speed hz\n");

    ret = ioctl(dev_spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &dev_spi_speed);
    if (ret == -1)
        LOG_ERROR("can't get max speed hz\n");

    LOG_INFO("spi mode: %d\n", dev_spi_mode);
    LOG_INFO("bits per word: %d\n", dev_spi_bits);
    LOG_INFO("max speed: %d Hz (%d KHz)\n", dev_spi_speed, dev_spi_speed/1000);
    LOG_INFO("over!\n");

    //write only 只写 只有先向export写入数字，/sys/class/gpio下才能生成gpioXXX文件
	exportGpio = open("/sys/class/gpio/export", O_WRONLY);
	if (exportGpio < 0)
	{
		puts("Cannot open GPIO to export it\n");
		exit(1);
	}
    write(exportGpio, "436", 4);//string -> const char *
    close(exportGpio);

    // Update the direction of the GPIO to be an output
	int directionfd;
    directionfd = open("/sys/class/gpio/gpio436/direction", O_RDWR);
	if (directionfd < 0)
	{
		puts("Cannot open GPIO direction it\n");
		exit(1);
	}
	write(directionfd, "out", 4);
	close(directionfd);
   
    gpioValuefd = open("/sys/class/gpio/gpio436/value", O_RDWR);
    if (gpioValuefd < 0)
	{
		puts("Cannot open GPIO value\n");
		exit(1);
	}
    write(gpioValuefd,"1", 2);
}
static void Spi_CS_High()
{
    write(gpioValuefd,"1", 2);
}
static void Spi_CS_Low()
{
    write(gpioValuefd,"0", 2);
}
static unsigned char Spi_Transfers(unsigned char *tx,unsigned char *rx,unsigned int len)
{
    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = len,
        .delay_usecs = 0,
        .speed_hz = 0,
        .bits_per_word = dev_spi_bits,
    };
    int ret;
    ret = ioctl(dev_spi_fd, SPI_IOC_MESSAGE(1), &tr); //SPI_IOC_MESSAGE(N),进行N次读写    //ret返回的是成功发送或者接受的字节数
    LOG_INFO("spi treasfer ret:%d\n",ret);
    if (ret != len)
    {
        LOG_ERROR("can't send spi message\n");
        return -1;
    }
    else
    {
        return 0;
    }
}



void ADXL345_ReadDevId()
{

    Spi_Init();
    
    unsigned char tx[] = {RCMD(0x00),0x00};
    printf("0x%02x 0x%02x\n",tx[0],tx[1]);
    unsigned char rx[10] = {0};
    Spi_CS_Low();
    Spi_Transfers(tx,rx,2);
    Spi_CS_High();

    for(int i=0;i<2;i++)
    {
        printf("0x%02x ",rx[i]);
    }
    printf("\n");
}

static void ADXL345_Write(unsigned char cmd,unsigned char data)
{
    memset(gtx,0,TXSIZE);
    memset(grx,0,RXSIZE);

    gtx[0]=WCMD(cmd);

    Spi_CS_Low();
    Spi_Transfers(gtx,grx,2);
    Spi_CS_High();

}

static void ADXL345_Read(unsigned char cmd)
{
    memset(gtx,0,TXSIZE);
    memset(grx,0,RXSIZE);

    gtx[0]=RCMD(cmd);
    
    Spi_CS_Low();
    Spi_Transfers(gtx,grx,2);
    Spi_CS_High();

}


void ADXL345_Init()
{
    Spi_Init();
    ADXL345_Read(DEVID);
    LOG_INFO("0x%02x 0x%02x",grx[0],grx[1]);
}



unsigned char Spi_SendConfig(unsigned char add,unsigned char data)
{
    int ret;
    unsigned char tx[1];
    unsigned char rx[1];
    tx[0]=add;
    ret = Spi_Transfers(tx,rx,2);
    if(ret != 0)
    {
        LOG_INFO("Write Config Add %02x ERROR",add);
        LOG_INFO("Device id %02x",rx[1]);
        exit(-1);
    }
    LOG_INFO("Device id %02x",rx[1]);
    memset(rx,0,1);
    tx[0] = data;
    ret = Spi_Transfers(tx,rx,2);
    if(ret != 0)
    {
        LOG_INFO("Write Config Add %02x Data %02x ERROR",add,data);
        exit(-1);
    }
    return 0;
}


// void ADXL345_Init()
// {
//     ///read device id
//     unsigned char tx[] = {DEVID,0x00,0x00,0x00,0x00};
//     unsigned char rx[5] = {0};
//     int ret = Spi_Transfers(tx,rx,2);
//     if(ret != 0)
//     {
//         LOG_ERROR("Get device id error");
//         LOG_INFO("%s",rx);
//     }

//     Spi_SendConfig(OFSX,0x00);//x轴偏移
//     Spi_SendConfig(OFSY,0x00);//y轴偏移
//     Spi_SendConfig(OFSZ,0x00);//z轴偏移

//     Spi_SendConfig(DATA_FORMAT,0x0B);//范围0-16g  SPI4线模式  右对齐
//     Spi_SendConfig(BW_RATE,0xFF);//输出速率 3200hz
//     Spi_SendConfig(POWER_CTL,0x08); //功耗设置 设置为测量模式

//     Spi_SendConfig(FIFO_CTL,0x00);//设置FIFO
//     Spi_SendConfig(INT_ENABLE,0x00);//设置中断使能
//     Spi_SendConfig(INT_MAP,0x00);//设置中断映射
// }


// void ADXL345_Read(TAdxl345Data* data)
// {
//     unsigned char buf[6];
//     unsigned char tx[1];
//     unsigned char rx[1];

//     tx[0]=0x32;
//     Spi_Transfers(tx,rx,1);
//     buf[0]=rx[0];
//     memset(rx,0,1);

//     tx[0]=0x33;
//     Spi_Transfers(tx,rx,1);
//     buf[1]=rx[0];
//     memset(rx,0,1);
    
//     tx[0]=0x34;
//     Spi_Transfers(tx,rx,1);
//     buf[2]=rx[0];
//     memset(rx,0,1);

//     tx[0]=0x35;
//     Spi_Transfers(tx,rx,1);
//     buf[3]=rx[0];
//     memset(rx,0,1);

//     tx[0]=0x36;
//     Spi_Transfers(tx,rx,1);
//     buf[4]=rx[0];
//     memset(rx,0,1);

//     tx[0]=0x37;
//     Spi_Transfers(tx,rx,1);
//     buf[5]=rx[0];
//     memset(rx,0,1);

//     data->acc_x = ((buf[1]<<8|buf[0]));
//     data->acc_y = ((buf[3]<<8|buf[2]));
//     data->acc_z = ((buf[5]<<8|buf[4]));

//     printf("X=%4.3f    m/s2   Y=%4.3f   m/s2   Z=%4.3f   m/s2 \r\n",data->acc_x*3.9/1000*9.8,data->acc_y*3.9/1000*9.8,data->acc_z*3.9/1000*9.8);
// }